package com.dshore.messagecenter.model.technology;

import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

/**
 * 短信验证码管理
 * 
 * @author
 * @version
 * @since
 */
public class SMSAuthCodeManager {
    static Logger logger = Logger.getLogger(SMSAuthCodeManager.class.getName());

    private static SMSAuthCodeManager manager = new SMSAuthCodeManager();

    private Map<String, AuthCode> codeMap = null;

    private static final long TIMEOUT = Constant.SMSCODE_TIME_OUT * 60 * 1000;

    /**
     * 私有化构造方法
     */
    private SMSAuthCodeManager() {

    }

    /**
     * SMSAuthCodeManager单例
     * 
     * @return SMSAuthCodeManager
     */
    public static SMSAuthCodeManager getInstance() {
        return manager;
    }

    /**
     * 清除失效的CODE，由SPRING定时任务调度
     */
    public void clean() {
        if (codeMap != null && codeMap.size() > 0) {
            AuthCode authCode = null;
            Calendar calnedar = Calendar.getInstance();
            for (Map.Entry<String, AuthCode> entry : codeMap.entrySet()) {
                authCode = entry.getValue();
                long result = calnedar.getTimeInMillis() - authCode.getCreateTime().getTime();

                // 超过时间，错误次数，标记清除
                if (result > TIMEOUT || result < 0 || authCode.getErrCount() > Constant.SMSCODE_ERR_COUNT || authCode.isCleanFlg()) {
                    codeMap.remove(authCode.getPhoneNumber());
                    logger.info("Clean the SMSCODE! phone:" + authCode.getPhoneNumber() + ",code:"+ authCode.getSmsCode());
                }
            }
        }
    }

    /**
     * 删除全部
     */
    public synchronized void cleanAll() {
        if (null != codeMap) {
            codeMap.clear();
        }
    }

    /**
     * 根据电话号码查询验证码
     * 
     * @param phone
     * @return AuthCode
     */
    public AuthCode getCode(String phone) {
        if (null == codeMap) {
            return null;
        }
        return codeMap.get(phone);
    }

    /**
     * 添加验证码
     * 
     * @param authCode
     * @return boolean
     */
    public synchronized boolean putCode(AuthCode authCode) {
        if (null == authCode || StringUtils.isEmpty(authCode.getPhoneNumber())
                || StringUtils.isEmpty(authCode.getSmsCode()) || (null == authCode.getCreateTime())) {
            return false;
        }
        if (null == codeMap) {
            // codeMap = new HashMap<String, AuthCode>();
            codeMap = new ConcurrentHashMap<String, AuthCode>();
        } else {
            if (codeMap.size() > Constant.SMS_CODE_MAX) {
                logger.warn("The SMSCODE MAP is full!");
                return false;
            }
        }
        codeMap.put(authCode.getPhoneNumber(), authCode);
        return true;
    }

    /**
     * 校验验证码是否成功
     * 
     * @param serialNumber
     * @param phoneNumber
     * @param smsType 短信类型
     * @return boolean
     */
    public String checkCode(String serialNumber, String phoneNumber, String smsType) {
        // 验证码没有值
        if (StringUtils.isEmpty(serialNumber)) {
            return "验证码没有值";
        }

        AuthCode authCode = SMSAuthCodeManager.getInstance().getCode(phoneNumber);
        // 根据手机号码，没有获得短信验证码
        if (null == authCode) {
            return "请获取验证码";
        } else {
            if (!smsType.equals(authCode.getSmsType())) {
                return "";
            }
            Calendar calnedar = Calendar.getInstance();
            long result = calnedar.getTimeInMillis() - authCode.getCreateTime().getTime();
            if(authCode.getErrCount() >= Constant.SMSCODE_ERR_COUNT){
                logger.info("The SMSCODE is invalid! phone:" + authCode.getPhoneNumber() + ",code:"
                        + authCode.getSmsCode());
                return "错误次数超过3次，请重新获取验证码";
            }
            if (result > TIMEOUT || result < 0) {
                logger.info("The SMSCODE is invalid! phone:" + authCode.getPhoneNumber() + ",code:"+ authCode.getSmsCode());
                 return "验证已超时，请重新获取验证码";
            }
            // 验证码不一致
            if (!serialNumber.equals(authCode.getSmsCode())) {
                // 错误次数加1
                authCode.addErrCount();
                return "验证码不正确";
            } else {
                // 已经无效
                if (authCode.isCleanFlg()) {
                    return "验证码已失效，请重新获取验证码";
                }
                // 验证成功了，就即时清除
                authCode.setCleanFlg(true);
                return "0";
            }
        }

    }
}
